package com.bw.tibjson;

import com.tibco.pe.plugin.Activity;
import com.tibco.pe.plugin.ActivityException;
import com.tibco.pe.plugin.ProcessContext;
import com.tibco.xml.data.primitive.ExpandedName;
import com.tibco.xml.datamodel.XiFactoryFactory;
import com.tibco.xml.datamodel.XiNode;
import com.tibco.xml.datamodel.helpers.XiSerializer;
import com.tibco.xml.schema.SmFactory;
import com.tibco.xml.schema.SmParticleTerm;
import com.tibco.xml.schema.SmSupport;
import com.tibco.xml.schema.build.MutableSupport;
import com.tibco.xml.schema.flavor.XSDL;
import com.tibco.xml.schema.parse.SmParseSupport;
import com.tibco.xml.xdata.InputData;
import java.io.IOException;
import java.io.StringReader;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.json.JSONException;
import org.json.XML;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 *
 * @author nMAX334
 * @version 0.2
 */
public class JSONRenderActivity extends Activity {

    //we need to set processContents="lax|skip" so that we can accept an "any" xml as input, otherwise it will fail validation.
    private static final String SCHEMA = "<?xml version = \"1.0\" encoding = \"UTF-8\"?>"
            + "<xsd:schema xmlns:xsd = \"http://www.w3.org/2001/XMLSchema\" elementFormDefault = \"qualified\">"
            + "<xsd:element name = \"jsonString\" type = \"xsd:string\"/>"
            + "<xsd:element name=\"XML\"><xsd:complexType><xsd:sequence><xsd:any processContents=\"lax\" namespace=\"##any\"/></xsd:sequence></xsd:complexType></xsd:element>"
            + "</xsd:schema>";
    private static final String OUTPUT_LABEL = "jsonString";
    private static final ExpandedName OUTPUT_NAME = ExpandedName.makeName(OUTPUT_LABEL);
    private SmParticleTerm outputTerm, inputTerm;

    public JSONRenderActivity() throws SAXException, IOException {
        StringReader stringReader = new StringReader(SCHEMA);
        try {
            inputTerm = SmSupport.getElement(SmParseSupport.parseSchema(new InputSource(stringReader)), "XML");
            outputTerm = MutableSupport.createElement(SmFactory.newInstance().createMutableSchema(), OUTPUT_LABEL, XSDL.STRING);
        } finally {
            stringReader.close();
        }
    }

    @Override
    public XiNode eval(ProcessContext pc, InputData id) throws ActivityException {
        XiNode xiNode = XiFactoryFactory.newInstance().createDocument();
        try {
            String xmlString = XiSerializer.serialize(id.getXiNode().getFirstChild().getFirstChild());// XML/root node
            Logger.getLogger(JSONParseActivity.class.getName()).log(Level.INFO, xmlString);

            xiNode.appendElement(OUTPUT_NAME, toJSON(xmlString));
        } catch (Exception ex) {
            Logger.getLogger(JSONParseActivity.class.getName()).log(Level.SEVERE, null, ex);
            throw new ActivityException(ex.getLocalizedMessage());
        }
        return xiNode;
    }

    @Override
    public SmParticleTerm getInputTerm() {
        return this.inputTerm;
    }

    @Override
    public SmParticleTerm getOutputTerm() {
        return this.outputTerm;
    }

    @Override
    public void destroy() throws Exception {
//        throw new UnsupportedOperationException("Not supported yet.");
    }

    private String toJSON(String xmlString) throws JSONException {
        String jsonString = null;
        try {
            jsonString = XML.toJSONObject(xmlString).toString();
            //remove excess
//            int beginIndex = jsonString.indexOf(':');
//            jsonString = jsonString.substring(beginIndex + 2, jsonString.length() - 2);
        } catch (JSONException ex) {
            Logger.getLogger(JSONParseActivity.class.getName()).log(Level.SEVERE, null, ex);
            throw ex;
        }
        return jsonString;
    }
}
